#include <Windows.h>
#include <commctrl.h>    
#include <iostream>
#include <GL/glew.h>
#include <GL/GL.h>
#include <GL/GLU.h>
#include "GL/glut.h"

//#include "./res/resource.h"

#include "utility.h"
#include "mesh.h"

#include "brush.h"

#include "shader.h"
#include "mcShader.h"
#include "model.h"
#include "view.h"
#include "mainView.h"
#include "glView.h"
#include "glMappingView.h"

#include "handler.h"
#include "mainHandler.h"
#include "glhandler.h"
#include "glMappingHandler.h"



CRITICAL_SECTION CriticalSection; 

int mainMessageLoop(HACCEL hAccelTable) ;

void init () ;

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
               LPSTR lpCmdLine, int nCmdShow)
{

	init();
	InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400) ;

	//Create the main model for the program 
	//Model model ("D:\\workspace\\data\\onetriangle.obj"); 
	//Model model ("D:\\workspace\\data\\3faces_cube3.obj"); 
	//Model model ("D:\\workspace\\data\\flattern.obj"); 
	//Model model ("D:\\workspace\\data\\girl_face_tri_tex.obj"); 
	Model model ("D:\\workspace\\data\\cube3.obj");
	//Model model ("D:\\Downloads\\OpenNL3.2.1\\build\\Release\\tex.obj"); 
	//Model model ("D:\\workspace\\data\\bigguy2.obj"); 
	//Model model ("D:\\workspace\\data\\concave.obj");
	//Model model ("D:\\workspace\\data\\cossphere.obj");
	//Model model ("D:\\workspace\\data\\densecube.obj");
	
	//Creat Main Frame
	MainView mainFrame(hInstance, L"Mesh Color Frame");
	MainHandler mainHandler (&mainFrame, & model); 
	mainFrame.setWindowStyleEx(WS_EX_WINDOWEDGE);
	mainFrame.setWidth(1200);
	mainFrame.setHeight(650);
	mainFrame.addListener(& mainHandler );
	mainFrame.create();
	
	//GLView glView (& model, hInstance, L"Model View", mainFrame.getHWND()); 
	GLView glCullingView(& model, hInstance, L"Model View", mainFrame.getHWND());
	GLHandler glHandler(&glCullingView, & model);
    glCullingView.setClassStyle(CS_OWNDC);
    glCullingView.setWindowStyle(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
    glCullingView.setWidth(800);
    glCullingView.setHeight(600);
	glCullingView.addListener(&glHandler);
	glCullingView.create();
	glCullingView.setWindowPos(0, 0, 500, 600); 
	
	
	GLMappingView glMappingView (& model, hInstance, L"Editor View", mainFrame.getHWND()); 
	GLMappingHandler glMappingHandler(&glMappingView, & model);
    glMappingView.setClassStyle(CS_OWNDC);
    glMappingView.setWindowStyle(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
    glMappingView.setWidth(800);
    glMappingView.setHeight(600);
	glMappingView.addListener(&glMappingHandler);
	glMappingView.create();
	glMappingView.setWindowPos(500, 0, 500, 600); 
	

	glCullingView.show();
	glMappingView.show();
	mainFrame.show(); 

	//Main message loop
    int retValue;
    HACCEL hAccelTable = 0;
	//Load Accelarate Key Table ;
    //hAccelTable = ::LoadAccelerators(hInst, MAKEINTRESOURCE(ID_ACCEL));
    retValue = mainMessageLoop(hAccelTable);

	//Delete Critical section
	DeleteCriticalSection(&CriticalSection);
    return retValue;
}

void init()
{
	INITCOMMONCONTROLSEX commonCtrls;
    commonCtrls.dwSize = sizeof(commonCtrls);
    commonCtrls.dwICC = ICC_UPDOWN_CLASS;
    ::InitCommonControlsEx(&commonCtrls);
}

int mainMessageLoop(HACCEL hAccelTable)
{
    HWND activeHandle;
    MSG msg;

    while(::GetMessage(&msg, 0, 0, 0) > 0)  
    {
        // determine the activated window is dialog box
        // skip if messages are for the dialog windows
        activeHandle = ::GetActiveWindow();
        if(::GetWindowLongPtr(activeHandle, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) // WS_EX_CONTROLPARENT is automatically added by CreateDialogBox()
        {
            if(::IsDialogMessage(activeHandle, &msg))
                continue;   // message handled, back to while-loop
        }
        if(!::TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }
    }
    return (int)msg.wParam;
}

